package gang.org.springframework.framework.metadata;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

final class GangAttributeMethods {

    private final Class<? extends Annotation> annotationType;
    private final Method[] attributeMethods;

    //TODO
    //private static final Map<Class<?extends Annotation>,GangAttributeMethods> cache = new GangConcurrentReferenceHashMap();

    private static final Map<Class<?extends Annotation>, GangAttributeMethods> cache = new ConcurrentHashMap<>();

    static GangAttributeMethods forAnnotationType(Class<? extends Annotation> annotationType){
        return cache.computeIfAbsent(annotationType,GangAttributeMethods::compute);
    }

    //TODO
    /**
     * @param annotationType {@link gang.org.springframework.boot.autoconfigure.GImport}
     * */
    private static GangAttributeMethods compute(Class<? extends Annotation> annotationType) {
        Method[] methods = annotationType.getDeclaredMethods();

        Arrays.sort(methods, methodComparator);

        return new GangAttributeMethods(annotationType,methods);
    }

    //TODO
    private GangAttributeMethods(Class<? extends Annotation> annotationType, Method[] attributeMethods)
    {
        this.annotationType = annotationType;
        this.attributeMethods = attributeMethods;
        for (int i = 0; i < attributeMethods.length; i++) {
            Method method = attributeMethods[i];
            Class<?> type = method.getReturnType();
        }
    }

    int size(){
        return this.attributeMethods.length;
    }

    Method get(int index)
    {
        return this.attributeMethods[index];
    }

    private static final Comparator<Method> methodComparator = (m1, m2) -> {

        if (m1 != null && m2 != null)
        {
            return m1.getName().compareTo(m2.getName());
        }

        return m1 != null ? -1 : 1;
    };

    public Method get(String name)
    {
        int index = indexOf(name);
        return index != -1 ? this.attributeMethods[index] : null;
    }

    public int indexOf(String name)
    {
        for (int i = 0; i < this.attributeMethods.length; i++) {

            if (this.attributeMethods[i].getName().equals(name)) {
                return i;
            }
        }

        return -1;
    }
}
